#ifndef _TENSOR_MAT19_H_
#define _TENSOR_MAT19_H_

#include <vector>
#include "pcg_def.h"

namespace TensorMat19 {

// Grid configuration parameters
struct GridParams {
    int imt;        // Number of points in x direction
    int jmt;        // Number of points in y direction
    int kmt;        // Number of points in z direction
    int resolution; // Resolution parameter (default: 1)
    
    bool is_global_grid; // true for global grid (lat-lon), false for local grid (Cartesian)
    
    // Calculated values
    int total_inner_points; // Total number of inner grid points (imt*jmt*kmt)
    int total_padded_points; // Total number of padded grid points (imt+2)*(jmt+2)*(kmt+2)
    
    // Initialize grid parameters
    GridParams(int resolution = 1, bool is_global = true);
    
    // Calculate indices for different grid representations
    int inner_index(int i, int j, int k) const;
    int padded_index(int i, int j, int k) const;
    
    // Get coordinates from linear index
    void get_coords(int linear_idx, int& i, int& j, int& k) const;
    
    // Debug info
    void print_info() const;
};

// 19-diagonal tensor format matrix
struct TensorMatrix {
    float* data;    // Matrix coefficients in tensor format: 19 x imt x jmt x kmt
    int num_diags;  // Number of diagonals (19)
    int size;       // Total size of the matrix
    
    GridParams grid;
    
    // Constructor and destructor
    TensorMatrix(const GridParams& grid_params);
    ~TensorMatrix();
    
    // Access element (m,i,j,k) in the tensor
    float& at(int m, int i, int j, int k);
    float at(int m, int i, int j, int k) const;
    
    // Initialize with random values
    void init_random();
    
    // Perform matrix-vector multiplication: y = A*x
    void multiply(const float* x, float* y) const;
    
    // Convert to CSR format
    void to_csr(CsrMatrix& csr) const;
};

// Boundary communication for vectors
void communicate_boundaries(float* vec, const GridParams& grid);

// Vector operations for the padded vectors
float dot_product(const float* x, const float* y, const GridParams& grid);
float norm_squared(const float* x, const GridParams& grid);

} // namespace TensorMat19

#endif // _TENSOR_MAT19_H_ 